package com.wing.common.utils;

import org.apache.commons.lang.StringUtils;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME;

/**
 * LocalDateTime工具类
 *
 * @author
 */
public class LocalDateTimeUtils {

    /**
     *  每天的秒数
     */
    public static final long DAY_SECONDS = 86400;
    //public static final long DAY_SECONDS = 1800;

    /**
     *  时间格式
     */
    public static final String PATTERN = "yyyy-MM-dd HH:mm:ss";

    //获取当前时间的LocalDateTime对象
    //LocalDateTime.now();

    //根据年月日构建LocalDateTime
    //LocalDateTime.of();

    //比较日期先后
    //LocalDateTime.now().isBefore(),
    //LocalDateTime.now().isAfter(),

    private final static String REGEX_TIME = "^(\\d{10,13}|\\d{4}-\\d{2}-\\d{2}.\\d{2}:\\d{2}.*)$";

    public static LocalDateTime convert(String resolver) {
        if (Pattern.matches(REGEX_TIME, resolver)) {
            Instant instant;
            switch (resolver.length()) {
                case 10:
                    instant = Instant.ofEpochSecond(Long.parseLong(resolver));
                    return LocalDateTime.ofInstant(instant, ZoneId.of("GMT+8"));
                case 13:
                    instant = Instant.ofEpochMilli(Long.parseLong(resolver));
                    return LocalDateTime.ofInstant(instant, ZoneId.of("GMT+8"));
                default:
                    break;
            }

            if (resolver.endsWith("Z")) {
                return LocalDateTime.ofInstant(Instant.parse(resolver), ZoneId.of("GMT+8"));
            } else if (resolver.charAt(10) == 'T') {
                return LocalDateTime.parse(resolver, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
            } else if (resolver.charAt(10) == ' ') {
                return LocalDateTime.parse(resolver, new DateTimeFormatterBuilder()
                        .parseCaseInsensitive()
                        .append(ISO_LOCAL_DATE)
                        .appendLiteral(' ')
                        .append(ISO_LOCAL_TIME)
                        .toFormatter());
            }
        }
        return null;
    }

    /**
     * String转换为LocalDateTime
     *
     * @param dateTime 日期
     * @param pattern 时间格式
     * @return LocalDateTime
     */
    public static LocalDateTime convertStringToLDT(String dateTime, String pattern) {
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern(StringUtils.isBlank(pattern) ? PATTERN : pattern)
                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                .parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
                .toFormatter();

        return LocalDateTime.parse(dateTime, formatter);
    }

    /**
     * Date转换为LocalDateTime
     *
     * @param date
     *
     * @return LocalDateTime
     */
    public static LocalDateTime convertDateToLDT(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * LocalDateTime转换为Date
     *
     * @param localDateTime
     *
     * @return Date
     */
    public static Date convertLocalDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取指定日期的毫秒
     *
     * @param localDateTime
     *
     * @return Long
     */
    public static Long getMilliByTime(LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 获取指定日期的秒
     *
     * @param localDateTime
     *
     * @return Long
     */
    public static Long getSecondsByTime(LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
    }

    /**
     * 获取指定时间的指定格式
     *
     * @param localDateTime
     * @param pattern
     *
     * @return String
     */
    public static String formatTime(LocalDateTime localDateTime, String pattern) {
        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 获取当前时间的指定格式
     *
     * @param pattern
     *
     * @return String
     */
    public static String formatNow(String pattern) {
        return  formatTime(LocalDateTime.now(), pattern);
    }

    /**
     * 日期加上一个数,根据field不同加不同值,field为ChronoUnit.*
     *
     * @param localDateTime
     * @param number
     * @param field
     *
     * @return LocalDateTime
     */
    public static LocalDateTime plus(LocalDateTime localDateTime, long number, TemporalUnit field) {
        return localDateTime.plus(number, field);
    }

    /**
     * 日期减去一个数,根据field不同减不同值,field参数为ChronoUnit.*
     *
     * @param localDateTime
     * @param number
     * @param field
     *
     * @return LocalDateTime
     */
    public static LocalDateTime minus(LocalDateTime localDateTime, long number, TemporalUnit field){
        return localDateTime.minus(number,field);
    }

    /**
     * * 获取两个日期的差
     * field参数为ChronoUnit.*
     * @param startTime
     * @param endTime
     * @param field 单位(年月日时分秒)
     * @return
     */
    public static long betweenTwoTime(LocalDateTime startTime, LocalDateTime endTime, ChronoUnit field) {
        Period period = Period.between(LocalDate.from(startTime), LocalDate.from(endTime));
        if (field == ChronoUnit.YEARS){
            return period.getYears();
        }
        if (field == ChronoUnit.MONTHS){
            return period.getYears() * 12 + period.getMonths();
        }
        return field.between(startTime, endTime);
    }

    /**
     * 获取一天的开始时间
     *
     * @param localDateTime
     *
     * @return
     */
    public static LocalDateTime getDayStart(LocalDateTime localDateTime) {
        return localDateTime.withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
    }

    /**
     * 获取一天的结束时间
     *
     * @param localDateTime
     *
     * @return
     */
    public static LocalDateTime getDayEnd(LocalDateTime localDateTime) {
        return localDateTime.withHour(23)
                .withMinute(59)
                .withSecond(59)
                .withNano(999999999);
    }

    /**
     * 获取昨天的开始时间
     *
     * @param
     *
     * @return
     */
    public static LocalDateTime getYesterdayStart() {
        LocalDateTime localDateTime = minus(LocalDateTime.now(), 1, ChronoUnit.DAYS);
        return localDateTime.withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
    }

    /**
     * 获取昨天的结束时间
     *
     * @param
     *
     * @return
     */
    public static LocalDateTime getYesterdayEnd() {
        LocalDateTime localDateTime = minus(LocalDateTime.now(), 1, ChronoUnit.DAYS);
        return localDateTime.withHour(23)
                .withMinute(59)
                .withSecond(59)
                .withNano(999999999);
    }

    /**
     * 获取今天的开始时间
     *
     * @param
     *
     * @return
     */
    public static LocalDateTime getTodayStart() {
        return getDayStart(LocalDateTime.now());
    }

    /**
     * 获取今天的结束时间
     *
     * @param
     *
     * @return
     */
    public static LocalDateTime getTodayEnd() {
        return getDayEnd(LocalDateTime.now());
    }

    /**
     * 获取明天的开始时间
     *
     * @param
     *
     * @return
     */
    public static LocalDateTime getTomorrowStart() {
        LocalDateTime localDateTime = plus(LocalDateTime.now(), 1, ChronoUnit.DAYS);
        return localDateTime.withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
    }

    /**
     * 获取明天的结束时间
     *
     * @param
     *
     * @return
     */
    public static LocalDateTime getTomorrowEnd() {
        LocalDateTime localDateTime = plus(LocalDateTime.now(), 1, ChronoUnit.DAYS);
        return localDateTime.withHour(23)
                .withMinute(59)
                .withSecond(59)
                .withNano(999999999);
    }

    /**
    * 获取昨天的开始时间
    *
    * @param
    *
    * @return
    */
    public static LocalDateTime getYesterdayStartByDaySeconds() {
       long nowDayCount = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) / DAY_SECONDS;
       Long yesterdayStartSeconds = new Long((nowDayCount - 1) * DAY_SECONDS);
       return LocalDateTime.ofEpochSecond(yesterdayStartSeconds,0, ZoneOffset.ofHours(8));
    }

    /**
    * 获取昨天的结束时间
    *
    * @param
    *
    * @return
    */
    public static LocalDateTime getYesterdayEndByDaySeconds() {
       long nowDayCount = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) / DAY_SECONDS;
       Long yesterdayEndSeconds = new Long(nowDayCount * DAY_SECONDS - 1);
       return LocalDateTime.ofEpochSecond(yesterdayEndSeconds,0, ZoneOffset.ofHours(8));
    }

    /**
    * 获取今天的开始时间
    *
    * @param
    *
    * @return
    */
    public static LocalDateTime getTodayStartByDaySeconds() {
       long nowDayCount = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) / DAY_SECONDS;
       Long todayStartSeconds = new Long(nowDayCount * DAY_SECONDS + 1);
       return LocalDateTime.ofEpochSecond(todayStartSeconds,0, ZoneOffset.ofHours(8));
    }

    /**
    * 获取今天的结束时间
    *
    * @param
    *
    * @return
    */
    public static LocalDateTime getTodayEndByDaySeconds() {
       long nowDayCount = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) / DAY_SECONDS;
       Long todayEndSeconds = new Long((nowDayCount + 1) * DAY_SECONDS - 1);
       return LocalDateTime.ofEpochSecond(todayEndSeconds,0, ZoneOffset.ofHours(8));
    }

    /**
     * 获取指定宽度的开始时间
     *
     * @param localDateTime   当地日期时间
     * @param intervalSeconds 间隔几秒
     * @return {@link LocalDateTime}
     */
    public static LocalDateTime getStartTimeBySeconds(LocalDateTime localDateTime, long intervalSeconds) {
        long count = localDateTime.toEpochSecond(ZoneOffset.of("+8")) / intervalSeconds;
        Long startSeconds = new Long(count * intervalSeconds + 1);
        return LocalDateTime.ofEpochSecond(startSeconds,0, ZoneOffset.ofHours(8));
    }

    /**
     * 获取指定宽度的的结束时间
     *
     * @param localDateTime   当地日期时间
     * @param intervalSeconds 间隔几秒
     * @return {@link LocalDateTime}
     */
    public static LocalDateTime getEndTimeBySeconds(LocalDateTime localDateTime, long intervalSeconds) {
        long count = localDateTime.toEpochSecond(ZoneOffset.of("+8")) / intervalSeconds;
        Long endSeconds = new Long((count + 1) * intervalSeconds - 1);
        return LocalDateTime.ofEpochSecond(endSeconds,0, ZoneOffset.ofHours(8));
    }

    /**
     * 获取指定宽度的的切片时间
     *
     * @param startTime       开始时间
     * @param endTime         结束时间
     * @param intervalSeconds 间隔几秒
     * @return {@link List<LocalDateTime>}
     */
    public static List<LocalDateTime> getSliceListBySeconds(LocalDateTime startTime, LocalDateTime endTime, long intervalSeconds) {
        List<LocalDateTime> list = new ArrayList<>();
        list.add(startTime);
        getSliceListBySeconds(startTime, endTime, intervalSeconds, list);
        list.add(endTime);
        return list;
    }

    /**
     * 获取指定宽度的的切片时间
     *
     * @param startTime       开始时间
     * @param endTime         结束时间
     * @param intervalSeconds 间隔几秒
     * @param list            列表
     * @return {@link List<LocalDateTime>}
     */
    public static List<LocalDateTime> getSliceListBySeconds(LocalDateTime startTime, LocalDateTime endTime, long intervalSeconds, List<LocalDateTime> list) {
        long count = startTime.toEpochSecond(ZoneOffset.of("+8")) / intervalSeconds;
        Long endSeconds = new Long((count + 1) * intervalSeconds);
        LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(endSeconds,0, ZoneOffset.ofHours(8));
        if(localDateTime.isBefore(endTime)){
            list.add(localDateTime);
            getSliceListBySeconds(localDateTime, endTime, intervalSeconds, list);
        }
        return list;
    }

    /**
    * 获取昨天的天数
    *
    * @param
    *
    * @return
    */
    public static Long getYesterdayDayCountBySeconds() {
       return new Long(getYesterdayStartByDaySeconds().toEpochSecond(ZoneOffset.of("+8")) / DAY_SECONDS);
    }

    public static boolean judgeTimeRange(LocalDateTime nowTime, LocalDateTime startTime, LocalDateTime endTime){
        if(nowTime.isAfter(startTime) && nowTime.isBefore(endTime)){
            return true;
        }
        return false;
    }

    /**
     * 获取当前年月: 2023-12
     * @return
     */
    public static String getCurentYearMonth(){
        // 获软当就日期和时间
        Calendar calendar = Calendar.getInstance();
        // 将当前日期减去一个月
        calendar.add(Calendar.MONTH,+0);
        // 蓓式化日期

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");

        String previousMonth = dateFormat.format(calendar.getTime());

        System.out.println("上一个月的日期:"+ previousMonth);

        return previousMonth;
    }

    /**
     * 获取当年上一月: 2023-11
     * @return
     */
    public static String getPreviousYearMonth(){
        // 获软当就日期和时间
        Calendar calendar = Calendar.getInstance();
        // 将当前日期减去一个月
        calendar.add(Calendar.MONTH,-1);
        // 蓓式化日期

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM");

        String previousMonth = dateFormat.format(calendar.getTime());

        System.out.println("上一个月的日期:"+ previousMonth);

        return previousMonth;
    }

    public static void main(String[] args) {
        //LocalDateTime start = LocalDateTime.of(2021, 10, 18, 20, 13, 20);
        //LocalDateTime end = LocalDateTime.of(2021, 10, 18, 21, 23, 20);
        //List<LocalDateTime> sliceListBySeconds = getSliceListBySeconds(start, end, 10 * 60);
        //for(LocalDateTime localDateTime : sliceListBySeconds){
        //    System.out.println("--------------:" + localDateTime);
        //}
        //LocalDateTime nowTime = convertStringToLDT("2021-03-01 00:00:01", LocalDateTimeUtils.PATTERN);
        //LocalDateTime startTime = convertStringToLDT("2021-03-01 00:00:00", LocalDateTimeUtils.PATTERN);
        //LocalDateTime endTime = convertStringToLDT("2021-03-31 23:59:59", LocalDateTimeUtils.PATTERN);
        Integer accountDay = 23;
        String startCreateTime = LocalDateTimeUtils.getPreviousYearMonth() + "-" + accountDay + " 00:00:00";
        String endCreateTime = LocalDateTimeUtils.getCurentYearMonth() + "-" + accountDay + " 00:00:00";
        System.out.println(startCreateTime);
        System.out.println(endCreateTime);
    }
}
